package studio.raptor.dispatcher.server.listeners;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import studio.raptor.dispatcher.scheduler.ServerScheduler;
import studio.raptor.dispatcher.scheduler.config.TaskConfig;
import studio.raptor.dispatcher.server.dto.Consumer;
import studio.raptor.dispatcher.server.event.ConsumerCreationEvent;
import studio.raptor.dispatcher.server.event.ConsumerUpdatedEvent;

/**
 * 分发器任务节点监听
 *
 * @author jack
 * @since 1.0
 */
@Component
public class ServerTaskListener implements TreeCacheListener {

  private static final Logger log = LoggerFactory.getLogger(ServerTaskListener.class);

  @Autowired
  ApplicationEventPublisher applicationEventPublisher;

  @Autowired
  ServerScheduler serverScheduler;


  @Override
  public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
    ChildData data = event.getData();
    switch (event.getType()) {
      case NODE_ADDED:
        handleNodeAdded(data, client);
        break;
      case NODE_REMOVED:
        //todo
        break;
      case NODE_UPDATED:
        handleNodeUpdated(data);
        break;

      default:
        break;
    }

  }

  private void handleNodeAdded(ChildData data, CuratorFramework client) {
    List<String> paths = Lists
        .newArrayList(Splitter.on("/").trimResults().omitEmptyStrings().split(data.getPath()));
    //新增分发器
    if (paths.size() < 3) {
      //todo

    } else {
      addTask(data, client);
    }
  }

  private void handleNodeUpdated(ChildData data) {
    List<String> paths = Lists
        .newArrayList(Splitter.on("/").trimResults().omitEmptyStrings().split(data.getPath()));
    //分发器状态更新
    if (paths.size() < 3) {
      //todo

    } else {
      updateTask(data);
    }
  }

  private void addTask(ChildData data, CuratorFramework client) {
    Preconditions.checkArgument(data.getData() != null, "the task state no null or empty");
    String task = Lists.newArrayList(Splitter.on("/").trimResults().split(data.getPath())).get(3);
    if (!task.contains("-")) {
      return;
    }
    String code = task.split("-")[0];
    Integer kindId = Integer.valueOf(task.split("-")[1]);
    boolean state = new String(data.getData()).equals("start") ? true : false;
    TaskConfig taskConfig = serverScheduler.getTaskConfig(code, kindId);

    ConsumerCreationEvent consumerCreationEvent = consumerCreationEvent(taskConfig, state);
    applicationEventPublisher.publishEvent(consumerCreationEvent);

  }

  private void updateTask(ChildData data) {
    Preconditions.checkArgument(data.getData() != null, "the task state no null or empty");
    String task = Lists.newArrayList(Splitter.on("/").trimResults().split(data.getPath())).get(3);
    String code = task.split("-")[0];
    Integer kindId = Integer.valueOf(task.split("-")[1]);
    boolean state = new String(data.getData()).equals("start") ? true : false;
    TaskConfig taskConfig = serverScheduler.getTaskConfig(code, kindId);

    ConsumerUpdatedEvent consumerUpdatedEvent = consumerUpdatedEvent(taskConfig,
        state);
    applicationEventPublisher.publishEvent(consumerUpdatedEvent);

  }

  private ConsumerUpdatedEvent consumerUpdatedEvent(TaskConfig taskConfig, boolean state) {
    Consumer consumer = consumer(taskConfig, state);
    return new ConsumerUpdatedEvent(this, consumer);
  }

  private ConsumerCreationEvent consumerCreationEvent(TaskConfig taskConfig, boolean state) {
    Consumer consumer = consumer(taskConfig, state);
    return new ConsumerCreationEvent(this, consumer);
  }

  private Consumer consumer(TaskConfig taskConfig, boolean state) {
    Consumer consumer = new Consumer();
    consumer.setCode(taskConfig.getCode());
    consumer.setName(taskConfig.getName());
    consumer.setKindId(taskConfig.getKindId());
    consumer.setEventType(taskConfig.getType());
    consumer.setState(state);
    consumer.setSort(taskConfig.isSort());
    consumer.setEventName(taskConfig.getEventName());
    return consumer;

  }
}